package com.cvc.tracker;

import java.io.File;

import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.view.MotionEvent;
import android.webkit.MimeTypeMap;

class Sample4View extends SampleViewBase {

	private static final String TAG = "CVC::S4V";

	private Bitmap mBitmap;
	private Mat mYuv;
	private Mat mRgba;
	private Mat mGraySubmat;
	private Mat mPreviousGraySubmat;
	private Mat mIntermediateMat;

	private ViewMode mViewMode;
	private ViewMode mPreviousViewMode;
	

	private Bitmap mMarkerBmp;
	private Mat mMarkerMat;
	private MediaMetadataRetriever retriever = null;
	private Bitmap mOverlapBmp;
	private Mat mOverlapMat;
	private Bitmap mOverlapAlphaBmp;
	private Mat mOverlapAlphaMat;
	private int totalTimeVideo = 0;
	private int currTimeVideo = 0;
	private int discartImage = 0;

	volatile boolean touched = false;

	public Sample4View(Context context) {
		super(context);
		mViewMode = ViewMode.CANNY;
		mPreviousViewMode = ViewMode.CANNY;

	}

	private void createMediaRetriever(String path) {

		retriever = new MediaMetadataRetriever();
		try {
			retriever.setDataSource(path);
			String duration = retriever
					.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
			totalTimeVideo = Integer.parseInt(duration);
			currTimeVideo = 0;
			Log.i(TAG, "duration video:" + duration);// just to test
			mOverlapBmp = retriever.getFrameAtTime();// just to
			Log.i(TAG, "altura video:" + mOverlapBmp.getHeight());// just to
																	// test

		} catch (RuntimeException ex) {
			// Assume this is a corrupt video file.
		} finally {

		}
	}

	private void updateOverlapImage() {
		if (retriever != null) {
			try {
				if(mOverlapBmp != null)
				{mOverlapBmp.recycle();}
				mOverlapBmp = null;
				mOverlapMat.setTo(new Scalar(0.0,0.0,0.0,0.0));
				
				mOverlapBmp = retriever.getFrameAtTime(currTimeVideo,MediaMetadataRetriever.OPTION_CLOSEST);
			} catch (RuntimeException ex) {
				// Assume this is a corrupt video file.
			} finally {
				
			}
			if(currTimeVideo > 601 && currTimeVideo < 1201)
			Utils.bitmapToMat(mOverlapBmp , mOverlapMat);
			setImageToOverlap(mOverlapMat.nativeObj);

			currTimeVideo = (currTimeVideo + 300) % totalTimeVideo;
			Log.i(TAG, "current time:" + currTimeVideo );
		}

	}

	@Override
	protected void onPreviewStared(int previewWidtd, int previewHeight) {
		// initialize Mats before usage
		mYuv = new Mat(getFrameHeight() + getFrameHeight() / 2,
				getFrameWidth(), CvType.CV_8UC1);
		mGraySubmat = mYuv.submat(0, getFrameHeight(), 0, getFrameWidth());
		mPreviousGraySubmat = new Mat();

		mRgba = new Mat();
		mIntermediateMat = new Mat();
		
		File baseSdcard = Environment.getExternalStorageDirectory();
		String url = baseSdcard.getPath() + "/paprika/marker.png";
		mMarkerBmp = BitmapFactory.decodeFile(url);
		mMarkerBmp.getHeight();
		Log.i(TAG, "marcador resolucao " + mMarkerBmp.getHeight() + " x " + mMarkerBmp.getWidth());
		mMarkerMat = new Mat();
		Utils.bitmapToMat(mMarkerBmp, mMarkerMat);
		loadMarker(mMarkerMat.nativeObj);
		
		url = baseSdcard.getPath() + "/paprika/overlap.png";
		mOverlapBmp = BitmapFactory.decodeFile(url);
		mOverlapMat = new Mat();
		Utils.bitmapToMat(mOverlapBmp, mOverlapMat);
				
		setImageToOverlap(mOverlapMat.nativeObj);
		
		url = baseSdcard.getPath() + "/paprika/overlap_alpha.png";
		mOverlapAlphaBmp = BitmapFactory.decodeFile(url);
		if(mOverlapAlphaBmp != null)
		{
			mOverlapAlphaMat = new Mat();
			Utils.bitmapToMat(mOverlapAlphaBmp, mOverlapAlphaMat);
			setImageToOverlapAlpha(mOverlapAlphaMat.nativeObj);
		}
		
		
		
		// using a video..	
		//url = baseSdcard.getPath() + "/paprika/videoDetecta.mp4";
		//mOverlapMat = new Mat();
		//createMediaRetriever(url);

		mBitmap = Bitmap.createBitmap(previewWidtd, previewHeight,
				Bitmap.Config.ARGB_8888);
		Log.i(TAG, "resolucao " + getFrameHeight() + " x " + getFrameWidth());
	}

	@Override
	protected void onPreviewStopped() {

		if (mBitmap != null) {
			mBitmap.recycle();
			mBitmap = null;
		}

		// Explicitly deallocate Mats
		if (mYuv != null)
			mYuv.release();
		if (mRgba != null)
			mRgba.release();
		if (mGraySubmat != null)
			mGraySubmat.release();
		if (mIntermediateMat != null)
			mIntermediateMat.release();
		if (mMarkerMat != null)
			mMarkerMat.release();
		if (mOverlapMat != null)
			mOverlapMat.release();

		mYuv = null;
		mRgba = null;
		mGraySubmat = null;
		mIntermediateMat = null;
		mMarkerMat = null;
		mOverlapMat = null;

		try {
			retriever.release();
		} catch (RuntimeException ex) {
			// Ignore failures while cleaning up.
		}

	}

	public boolean onTouchEvent(MotionEvent event) {
		touched = true;
		return true;
	}

	@Override
	protected Bitmap processFrame(byte[] data) {
		if (discartImage > 0)
		{
			--discartImage;
			return mBitmap;
		}
		
		mYuv.put(0, 0, data);

		if (touched) {
			restart();
			touched = false;
		}
		switch (mViewMode) {
		case CANNY:
			Imgproc.Canny(mGraySubmat, mIntermediateMat, 80, 100);
			Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2BGRA,
					4);
			break;
		case NATURAL:
			loadMarker(mMarkerMat.nativeObj);
			Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGB, 4);
			detect(mGraySubmat.getNativeObjAddr(), mRgba.getNativeObjAddr(),
					mPreviousGraySubmat.getNativeObjAddr(), 0, 1, 1);
			mGraySubmat.copyTo(mPreviousGraySubmat);
			break;
		case CHESS:
			Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGB, 4);
			detect(mGraySubmat.getNativeObjAddr(), mRgba.getNativeObjAddr(),
					mPreviousGraySubmat.getNativeObjAddr(), 0, 0, 1);
			mGraySubmat.copyTo(mPreviousGraySubmat);
			break;
		case CHESS_KLT:
			Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGB, 4);
			detect(mGraySubmat.getNativeObjAddr(), mRgba.getNativeObjAddr(),
					mPreviousGraySubmat.getNativeObjAddr(), 1, 0, 1);
			mGraySubmat.copyTo(mPreviousGraySubmat);
			mPreviousViewMode = ViewMode.CHESS_KLT;
			break;
		case NATURAL_KLT:
			//updateOverlapImage();
			Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGB, 4);
			detect(mGraySubmat.getNativeObjAddr(), mRgba.getNativeObjAddr(),
					mPreviousGraySubmat.getNativeObjAddr(), 1, 1, 1);
			mGraySubmat.copyTo(mPreviousGraySubmat);
			mPreviousViewMode = ViewMode.NATURAL_KLT;			
			break;
		case RESTART:
			restart();
			if (mPreviousViewMode == ViewMode.NATURAL_KLT)
				mViewMode = ViewMode.NATURAL_KLT;
			else if (mPreviousViewMode == ViewMode.NATURAL_KLT)
				mViewMode = ViewMode.CHESS_KLT;
			break;
		case DETECTION:
			
			Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGB, 4);
			int idDetected = detect(mGraySubmat.getNativeObjAddr(),
					mRgba.getNativeObjAddr(),
					mPreviousGraySubmat.getNativeObjAddr(), 0, 1, 0);
			mGraySubmat.copyTo(mPreviousGraySubmat);
			mViewMode = ViewMode.DETECTION;

			if (idDetected > 0) {
				mYuv.setTo(new Scalar(0.0,0.0,0.0,0.0));
				File baseSdcard = Environment.getExternalStorageDirectory();
				String url = baseSdcard.getPath() + "/paprika/videoDetecta.mp4";
				String extension = MimeTypeMap.getFileExtensionFromUrl(url);
				String mimeType = MimeTypeMap.getSingleton()
						.getMimeTypeFromExtension(extension);
				Intent mediaIntent = new Intent(Intent.ACTION_VIEW);
				mediaIntent.setDataAndType(Uri.parse(url), mimeType);
				getContext().startActivity(mediaIntent);
				discartImage = 3;
			}else
				discartImage = 1;

			break;
		}

		Bitmap bmp = mBitmap;

		try {
			Utils.matToBitmap(mRgba, bmp);
		} catch (Exception e) {
			Log.e("org.opencv.samples.puzzle15",
					"Utils.matToBitmap() throws an exception: "
							+ e.getMessage());
			bmp.recycle();
			bmp = null;
		}

		return bmp;
	}

	public native void FindFeature(long matAddrGr, long matAddrRgba);

	public native void loadMarker(long matAddrRgba);

	public native int detect(long matAddrGr, long matAddrRgba,
			long matAddrPreviousGr, int useKlt, int useNatural, int useTracking);

	public native void restart();

	public native void setImageToOverlap(long matAddrRgba);
	
	public native void setImageToOverlapAlpha(long matAddrAlpha);

	static {
		System.loadLibrary("opencv_java");
		System.loadLibrary("mixed_sample");

	}

	public void setViewMode(ViewMode viewMode) {
		mViewMode = viewMode;
	}
}
